package com.drore.cloud.controller;

import com.drore.cloud.constant.LocalConstant;
import com.drore.cloud.domain.sys.RestMessage;
import com.drore.cloud.exception.ApiException;
import com.drore.cloud.jdbc.MultiDS;
import com.drore.cloud.sdkjdbc.core.JdbcRunner;
import com.drore.cloud.sdkjdbc.model.Pagination;
import com.drore.cloud.utils.GsonUtil;
import com.drore.cloud.utils.ThreadLocalHolder;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.sql.SQLException;
import java.util.*;

/***
 * 浙江卓锐科技股份有限公司 版权所有@Copyright 2016
 * 说明
 * 项目名称
 * @since:cloud-ims 1.0
 * @author <a href="mailto:baoec@drore.com">baoec@drore.com </a> 
 * 2018/07/02 15:33
 */
@Api("表发布模块")
@RequestMapping(value = "/dbm/resource/")
@RestController
public class IssueCtl {
    @Autowired
    private JdbcRunner run;
    @Autowired
    private MultiDS mult;

    /**
     * 资源发布
     *
     * CREATE TABLE "operation_log" (
     "operator"  TEXT,
     "operator_code"  TEXT,
     "create_time"  TEXT,
     "action"  TEXT,
     "before_balance"  REAL,
     "after_balance"  REAL,
     "ip"  TEXT,
     "id"  TEXT NOT NULL,
     "username"  TEXT,
     PRIMARY KEY ("id" ASC)
     );
     * ****/
    @RequestMapping(value = "/issue" ,method = {RequestMethod.POST, RequestMethod.GET})
    public RestMessage issue(String resource_id)  {
        Map<String, Object> sys_user_info = (Map<String, Object>) ThreadLocalHolder.getCurrentUser();
        String data_type = Objects.toString(sys_user_info.get("data_type"));
        JdbcRunner jdbc = mult.getSessionRunner(Objects.toString(sys_user_info.get("data_source_id")));

        RestMessage rm=new RestMessage();
        //1找到该资源信息
        Map<String, Object> resources_info = run.queryOne("resources_info", resource_id);
        //2找到该资源信息下的所有字段信息
        Pagination resource_detail_page = run.queryListByExample("resource_detail", ImmutableMap.of("fk_resource_id", resource_id), 1, 1000);
        //3将 获得的信息  组装成  发布的sql
        StringBuffer create_sql=new StringBuffer(" CREATE TABLE ");
        create_sql.append(Objects.toString(resources_info.get("r_name"))).append(" (");
        if(resource_detail_page.getCount()<=0){
            throw new ApiException("字段个数不足，无法发布");
        }
        List<Map<String,Object>> data = resource_detail_page.getData();
        //数据库 不同  建表方式不同  字段sql
        String field_sql = "";
        if(data_type.equals("sqlite")){
            field_sql = SqliteFieldSql(data);
        }else if(data_type.equals("mysql")){
            field_sql = MysqlFieldSql(data);
        }

        create_sql.append(field_sql).append(");");

        try {
            boolean b = jdbc.executSql(create_sql.toString());
            if(b){
                //创建成功后 修改资源的发布状态
                run.update("resources_info",ImmutableMap.of("id",resource_id,"r_status","issued"));

                //将最新的表结构 使用json格式存放至中间表
                String resource_detail = GsonUtil.create().toJson(resource_detail_page.getData());
                run.insert("redis_list_structure",ImmutableMap.of("resource_id",resource_id,"resource_detail",resource_detail));
            }
        } catch (SQLException e) {
            throw new ApiException(e.getLocalizedMessage());
        }
        return rm;
    }

    @ApiOperation("目前重新发布只支持 新增字段 其他等有空 再完善")
    @RequestMapping(value = "/re_issue" ,method = {RequestMethod.POST, RequestMethod.GET})
    public RestMessage re_issue(String resource_id)  {
        Map<String, Object> sys_user_info = (Map<String, Object>) ThreadLocalHolder.getCurrentUser();
        JdbcRunner jdbc = mult.getSessionRunner(Objects.toString(sys_user_info.get("data_source_id")));
        String data_type = Objects.toString(sys_user_info.get("data_type"));

        RestMessage rm=new RestMessage();
        //1去中间表获取 原先的表结构
        Map<String, Object> Middle = run.queryFirstByRName("redis_list_structure", ImmutableMap.of("resource_id", resource_id));
        String resource_detail = Objects.toString(Middle.get("resource_detail"));
        List<Map<String,Object>> Middle_list = GsonUtil.create().fromJson(resource_detail, List.class);
        //2 拿到现在的表结构
        Pagination resource_detail_page = run.queryListByExample("resource_detail", ImmutableMap.of("fk_resource_id", resource_id), 1, 1000);
        //3比对出不同的 地方
        List<Map<String,Object>> data = resource_detail_page.getData();

        ArrayList<Map<String,Object>> addlist = Lists.newArrayList();
        ArrayList<Map<String,Object>> editlist = Lists.newArrayList();
        ArrayList<Map<String,Object>> dellist = Lists.newArrayList();
        for (Map<String, Object> detail : data) {
            String detail_id = Objects.toString(detail.get("id"));
            String detail_rd_name = Objects.toString(detail.get("rd_name"));
            String detail_field_type = Objects.toString(detail.get("field_type"));
            String detail_rd_length = Objects.toString(detail.get("rd_length"));
            boolean b=true;
            boolean editb=false;
            for (Map<String, Object> mid : Middle_list) {
                String mid_id = Objects.toString(mid.get("id"));
                if(detail_id.equals(mid_id)){
                    //现在的字段 与中间表字段 匹配到   检测 字段名 字段类型 长度 是否改变
                    //检测 字段名
                    if(!detail_rd_name.equals(Objects.toString(mid.get("rd_name")))){
                        detail.put("old_rd_name",Objects.toString(mid.get("rd_name")));
                        editb=true;
                    }
                    //检测 字段类型
                    if(!detail_field_type.equals(Objects.toString(mid.get("field_type")))){
                        editb=true;
                    }
                    //检测 字段长度
                    if(!detail_rd_length.equals(Objects.toString(mid.get("rd_length")))){
                        editb=true;
                    }
                    b=false;
                }
            }
            //如果中间表没有 则放入待新增的字段列表中
            if(b){
                addlist.add(detail);
            }
//            //如果中间表没有 则放入待新增的字段列表中
//            if(!b){
//                dellist.add(detail);
//            }
            //如果字段有变动 则加入待更新的字段列表中
            if(editb){
                editlist.add(detail);
            }


        }
        //4拼接 sql
        Map<String, Object> resources_info = run.queryOne("resources_info", resource_id);
        String r_name = Objects.toString(resources_info.get("r_name"));
        ArrayList<String> sqls = Lists.newArrayList();

        //新增字段部分
        for (Map<String, Object> add : addlist) {
            StringBuffer alter_sql=new StringBuffer();
            alter_sql.append("alter table ").append(r_name).append(" add column ");
            String field_type = Objects.toString(add.get("field_type"));
            if(field_type.equals("VARCHAR")||field_type.equals("INTEGER")||field_type.equals("DECIMAL")){
                alter_sql.append(add.get("rd_name")).append("    ").append(add.get("field_type"));
                alter_sql.append("(").append(add.get("rd_length")).append(");");
            }else {
                alter_sql.append(add.get("rd_name")).append("    ").append(add.get("field_type")).append(";");
            }
            sqls.add(alter_sql.toString());
        }
        //修改字段部分
        //目前mysql 支持更新字段 sqlite不支持
        if(data_type.equals("mysql")){
            for (Map<String, Object> edit : editlist) {
                StringBuffer alter_sql=new StringBuffer();
                //字段名改变的情况下
                if(edit.get("old_rd_name")!=null){
                    alter_sql.append("alter table ").append(r_name).append(" CHANGE  ").append(edit.get("old_rd_name")).append("  ");
                }else {
                    //单纯更改字段类型的情况下
                    alter_sql.append("alter table ").append(r_name).append(" modify column ");
                }


                String field_type = Objects.toString(edit.get("field_type"));
                if(field_type.equals("VARCHAR")||field_type.equals("INTEGER")||field_type.equals("DECIMAL")){
                    alter_sql.append(edit.get("rd_name")).append("    ").append(edit.get("field_type"));
                    alter_sql.append("(").append(edit.get("rd_length")).append(");");
                }else {
                    alter_sql.append(edit.get("rd_name")).append("    ").append(edit.get("field_type")).append(";");
                }
                sqls.add(alter_sql.toString());
            }
        }

        //执行sql
        if(sqls.size()>0){
            try {
                boolean b = jdbc.executBatchSql(sqls.toArray(new String[]{}));
                if (b){
                    //5重新发布成功后  把最新的表结构  更新至中间表
                    String resource_detail_json = GsonUtil.create().toJson(resource_detail_page.getData());
                    run.update("redis_list_structure",ImmutableMap.of("id",Middle.get("id"),"resource_detail",resource_detail_json));
                }
            } catch (SQLException e) {
                if(e.getSQLState().equals("42S02")){
                    //如果发现表不存在 直接发布
                    return this.issue(resource_id);
                }
                throw new ApiException(e.getLocalizedMessage());
            }
        }


        return rm;
    }


    public String SqliteFieldSql(List<Map<String,Object>> resource_detail){
        //字段sql
        StringBuffer field_sql=new StringBuffer();
        int field_num=0;
        for (Map<String, Object> detail : resource_detail) {
            String rd_name = Objects.toString(detail.get("rd_name"));
            String field_type = Objects.toString(detail.get("field_type"));
            field_sql.append(field_num==0?"":",");
            field_sql.append(rd_name);
            field_sql.append("  ");
            field_sql.append(field_type);
            field_num++;
        }
        return field_sql.toString();
    }

    public String MysqlFieldSql(List<Map<String,Object>> resource_detail){
        //字段sql
        StringBuffer field_sql=new StringBuffer();
        int field_num=0;
        for (Map<String, Object> detail : resource_detail) {
            String rd_name = Objects.toString(detail.get("rd_name"));
            String field_type = Objects.toString(detail.get("field_type"));
            String rd_length = Objects.toString(detail.get("rd_length"));
            field_sql.append(field_num==0?"":",");
            field_sql.append(rd_name);
            field_sql.append("  ");
            if(field_type.equals("VARCHAR")||field_type.equals("INTEGER")||field_type.equals("DECIMAL")){
                field_sql.append(field_type);
                field_sql.append("(").append(rd_length).append(")");
            }else {
                field_sql.append(field_type);
            }

            field_num++;
        }
        return field_sql.toString();
    }
}
